iT邦幫忙

2026 iThome 鐵人賽

DAY 1
0
IT Operation

解構作業系統:30 天從 Process、Concurrency 到 Virtual Memory系列 第 1

Day 1|程式為什麼不能想做什麼就做什麼?從 User Mode 與 Kernel Mode 開始解構作業系統

  • 分享至 

  • xImage
  •  

關於我,為什麼想寫這個系列

嗨!我是目前讀數位相關科系的大三學生。
而作業系統就是其中一門讓我覺得「好像懂了,但仔細想又沒有真的懂」的課。
以前在寫程式的時候,我比較在意的是程式能不能跑、結果對不對。後來發現一個看似簡單的程式背後,還有很多事情正在發生:程式怎麼被執行?CPU 怎麼同時處理這麼多工作?不同程式為什麼不會輕易讀到彼此的記憶體?我們平常使用的檔案最後又是怎麼被管理的?

我想利用 30 天重新整理自己對作業系統的理解。比起單純整理名詞和定義,我更想從「為什麼要這樣設計?」以及「底層到底發生了什麼?」這兩個問題出發,慢慢拆解 Process、Thread、System Call、Concurrency、Scheduling、Virtual Memory、File System 等機制。
這個系列不會把這個定位成教科書或完整的 OS 教學,比較像是把這 30 天真正理解到的東西整理、記錄下來。
希望 30 天之後,能總結回答:

「一支程式從開始執行到結束,作業系統到底在背後做了什麼?」

那麼,Day 1 就先從 User Mode 和 Kernel Mode 開始。

前言:如果沒有作業系統的限制會怎樣?

平常寫 C、C++ 或其他程式時,我們很容易有一種感覺:程式就是「在電腦上執行」。
例如寫下一段程式:

#include <stdio.h>

int main() {
    printf("Hello World!\n");
    return 0;
}

執行後,畫面出現了 Hello World!。
看起來非常理所當然。

但仔細想想,有很多細節藏在裡面。
printf() 最後要把資料顯示在螢幕上,程式需要使用記憶體,也需要 CPU 執行指令。如果今天改成讀取檔案、接收鍵盤輸入或透過網路傳送資料,又會牽涉到更多硬體與系統資源。
那問題來了:

既然程式正在 CPU 上執行,為什麼不能"直接控制"這些東西?

更極端一點,如果任何程式都能任意存取記憶體、控制硬體,甚至修改作業系統本身的資料,會發生什麼事?

大概就是——整台電腦會變得非常危險。

這也是我想從這裡開始理解作業系統的原因。

1. CPU 並不是永遠用同等的權限執行程式

如果先把複雜的硬體細節簡化,作業系統課程通常會把執行狀態分成兩個主要概念:

User Mode(使用者模式)是一般應用程式所在的環境。
Kernel Mode(核心模式)則是作業系統核心執行時使用的高權限環境。

我們平常執行的瀏覽器、遊戲、文字編輯器,甚至自己寫的 C 程式,通常都不是以最高權限直接執行。


  低權限
  ┌─────────────────────────┐ 
  │       User Mode         │ 
  │                         │ 
  │  Browser / Game / IDE   │
  └────────────┬────────────┘
               │
               ▼ 受控制的入口
  ┌─────────────────────────┐ 
  │       Kernel Mode       │ 
  │                         │ 
  │ Process / MemoryFile    │
  │ System / Driver/Network ...   
  └────────────┬────────────┘             
               │
               ▼Hardware
  高權限

User Mode 的程式不能直接執行所有 CPU 指令,也不能隨意存取所有系統資源。


2. 為什麼一定要限制 User Mode?

假設今天完全沒有這層限制。
我寫了一個普通程式:

int main() {
    // 假設我可以任意操作整台電腦的硬體與記憶體
}

如果這個程式擁有和作業系統一樣的權限,它理論上可能:

  • 修改其他 Process 的記憶體
  • 改掉 Kernel 使用的資料
  • 任意操作硬體裝置
  • 關閉中斷
  • 修改記憶體管理相關設定
  • 讓其他程式甚至整個系統無法正常運作

一個普通的 Bug 就可能把整台系統一起拖下水。


3. Privileged Instructions:有些指令不能讓你直接執行

其中一個重要概念就是 Privileged Instruction(特權指令)。
某些會直接影響整個系統狀態的操作,只允許在較高權限的模式下執行。
例如與中斷控制、記憶體管理或特定硬體控制有關的操作,就不能隨便交給一般 User Mode 程式。

這個保護並不只是 OS 寫一句:
請應用程式不要亂碰硬體 :)

如果 User Mode 程式試圖執行不被允許的 privileged operation,CPU 不會單純到「相信程式知道自己在幹嘛」,而會觸發Exception,將控制權交回作業系統處理。


4. 那 User Mode 什麼都不能做,程式怎麼工作?

如果一般程式不能直接操作重要系統資源,那我們平常怎麼:
開啟檔案?讀鍵盤?傳送網路packet?建立新的 Process?配置某些系統資源?

答案是:
程式不能「自己直接做」,但可以「請 Kernel 幫它做」。
這就是為甚麼 System Call(系統呼叫) 存在。
...........................
User Program

│「我想讀這個檔案」

System Call


Kernel

│ 檢查是否合法、執行操作

Hardware / File System
...........................
Kernel 變成中間的管理者。
應用程式提出要求,Kernel 判斷:

  • 這個要求是否合法?
  • 這個 Process 有沒有權限?
  • 要怎麼安全地完成?
  • 完成之後要回傳什麼結果?

因此,System Call 就像是 User Program 向 Kernel 請求服務的一個受控制入口。


5. printf() 真的只是印出文字嗎?

回到最前面的程式:
printf("Hello World!\n");
看起來就是一個普通函式。
但 printf() 並不是直接命令螢幕硬體「把這幾個字畫出來」。
以一般 Unix-like 系統的概念來看,printf() 是 C standard library 提供的函式,而且通常還牽涉到 buffering。
當資料真的需要被輸出時,底層可能進一步透過像 write() 這樣的 system call,把資料交給 Kernel。
...........................

printf() 
│
▼ 
C Library
│ 
▼
write() / System Call 
──────── User Space / Kernel Space ────────
▼ 
Kernel
│ 
▼
相關的系統資源

...........................
printf() 可以先把資料放在 user-space buffer 裡,等到適當的時機才真正透過 system call 輸出。


6. User Space 和 Kernel Space 又是什麼?

它們和 User Mode / Kernel Mode 有關,但並不是完全相同的概念。
簡單來說:
User Mode / Kernel Mode:比較偏 CPU 執行時的"權限狀態"
User Space / Kernel Space:比較偏向程式與記憶體位址"空間的劃分"

另外這又帶出一個很有趣的問題:

如果每個程式都覺得自己擁有一大片連續的記憶體,但實際 RAM 明明是大家共用的,OS 到底怎麼做到的?
這就會一路牽涉到 Virtual Memory、Page Table、Memory Protection。

也是這個系列後面會拆開來看的內容。


今天的結論

第一天原本只是想理解 User Mode 和 Kernel Mode 的差別,但整理到最後,我覺得真正重要的不是背:

User Mode 權限低,Kernel Mode 權限高。

而是理解:

為什麼需要有這個權限差異?
:如果所有程式都能直接控制硬體與系統資源,那麼任何 Bug 或惡意程式都有可能影響整個系統。CPU 提供不同的執行權限,OS 利用這些硬體機制建立 Protection。

今天可以先留下這條:

Application

User Mode

System Call

Kernel Mode

Hardware / System Resources

不過這裡其實還有一個問題還沒回答:

System Call 發生的那一瞬間,CPU 到底做了什麼?
程式真的只是從 User Mode「跳」到 Kernel Mode 嗎?
CPU 怎麼知道該執行 Kernel 的哪一段程式?原本程式執行到哪裡又是怎麼被保存的?處理完之後,又怎麼安全地回到 User Mode?

這就是下一篇想繼續拆的東西。

Day 2:System Call:一個 read() 是怎麼進入 Kernel 的?


下一篇
Day 2|System Call:一個 read() 是怎麼進入 Kernel 的?
系列文
解構作業系統:30 天從 Process、Concurrency 到 Virtual Memory9
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言